home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / rotate.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-31  |  7.8 KB  |  386 lines

  1. /* rotate.c - image rotation
  2.  * 
  3.  *  Raster graphics library
  4.  * 
  5.  *  Copyright (c) 2000 Alfredo K. Kojima
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <X11/Xlib.h>
  28. #include "wraster.h"
  29.  
  30. #include <math.h>
  31.  
  32. #ifndef PI
  33. #define PI 3.14159265
  34. #endif
  35.  
  36.  
  37. static RImage *rotateImage(RImage *image, float angle);
  38.  
  39.  
  40. RImage *RRotateImage(RImage *image, float angle)
  41. {
  42.     RImage *img;
  43.     int nwidth, nheight;
  44.     int x, y;
  45.     int bpp = image->format == RRGBAFormat ? 4 : 3;
  46.  
  47.     angle = ((int)angle % 360) + (angle - (int)angle);
  48.     
  49.     if (angle == 0.0) {
  50.     return RCloneImage(image);
  51.     
  52.     } else if (angle == 90.0) {
  53.     nwidth = image->height;
  54.     nheight = image->width;
  55.  
  56.     img = RCreateImage(nwidth, nheight, True);
  57.     if (!img) {
  58.         return NULL;
  59.     }
  60.     
  61.     if (bpp == 3) {
  62.         unsigned char *optr, *nptr;
  63.         unsigned offs;
  64.  
  65.  
  66.         offs = nwidth * 4;
  67.         
  68.         optr = image->data;
  69.         nptr = img->data;
  70.  
  71.         for (x = 0; x < nwidth; x++) {
  72.         nptr = img->data + x*4;
  73.         for (y = nheight; y; y--) {
  74.             nptr[0] = *optr++;
  75.             nptr[1] = *optr++;
  76.             nptr[2] = *optr++;
  77.             nptr[3] = 255;
  78.  
  79.             nptr += offs;
  80.         }
  81.         }
  82.     } else {
  83.         unsigned *optr, *nptr;
  84.         unsigned *p;
  85.  
  86.         optr = (unsigned*)image->data;
  87.         p = (unsigned*)img->data;
  88.         for (x = 0; x < nwidth; x++) {
  89.         nptr = p++;
  90.         for (y = nheight; y; y--) {
  91.             *nptr = *optr++;
  92.             nptr += nwidth;
  93.         }
  94.         }
  95.     }
  96.     } else if (angle == 180.0) {
  97.     
  98.     nwidth = image->width;
  99.     nheight = image->height;
  100.     img = RCreateImage(nwidth, nheight, True);
  101.     if (!img) {
  102.         return NULL;
  103.     }
  104.     
  105.     if (bpp == 3) {
  106.         unsigned char *optr, *nptr;
  107.  
  108.         optr = image->data;
  109.         nptr = img->data + nwidth * nheight * 4 - 4;
  110.  
  111.         for (y = 0; y < nheight; y++) {
  112.         for (x = 0; x < nwidth; x++) {
  113.             nptr[0] = optr[0];
  114.             nptr[1] = optr[1];
  115.             nptr[2] = optr[2];
  116.             nptr[3] = 255;
  117.         
  118.             optr += 3;
  119.             nptr -= 4;
  120.         }
  121.         }
  122.     } else {
  123.         unsigned *optr, *nptr;
  124.         
  125.         optr = (unsigned*)image->data;
  126.         nptr = (unsigned*)img->data + nwidth * nheight - 1;
  127.         
  128.         for (y = nheight*nwidth-1; y >= 0; y--) {
  129.         *nptr = *optr;
  130.         optr++;
  131.         nptr--;
  132.         }
  133.     }
  134.     } else if (angle == 270.0) {
  135.     nwidth = image->height;
  136.     nheight = image->width;
  137.  
  138.     img = RCreateImage(nwidth, nheight, True);
  139.     if (!img) {
  140.         return NULL;
  141.     }
  142.     
  143.     if (bpp == 3) {
  144.         unsigned char *optr, *nptr;
  145.         unsigned offs;
  146.  
  147.  
  148.         offs = nwidth * 4;
  149.         
  150.         optr = image->data;
  151.         nptr = img->data;
  152.  
  153.         for (x = 0; x < nwidth; x++) {
  154.         nptr = img->data + x*4;
  155.         for (y = nheight; y; y--) {
  156.             nptr[0] = *optr++;
  157.             nptr[1] = *optr++;
  158.             nptr[2] = *optr++;
  159.             nptr[3] = 255;
  160.  
  161.             nptr += offs;
  162.         }
  163.         }
  164.     } else {
  165.         unsigned *optr, *nptr;
  166.         unsigned *p;
  167.  
  168.         optr = (unsigned*)image->data;
  169.         p = (unsigned*)img->data + nwidth*nheight;
  170.         for (x = 0; x < nwidth; x++) {
  171.         nptr = p--;
  172.         for (y = nheight; y; y--) {
  173.             *nptr = *optr++;
  174.             nptr -= nwidth;
  175.         }
  176.         }
  177.     }
  178.     } else {
  179.     img = rotateImage(image, angle);
  180.     }
  181.     
  182.     return img;
  183. }
  184.  
  185.  
  186.  
  187.  
  188. /*
  189.  * Image rotation through Bresenham's line algorithm:
  190.  * 
  191.  * If a square must be rotate by angle a, like in:
  192.  *  _______
  193.  * |    B  |
  194.  * |   /4\ |     
  195.  * |  /3 8\|
  196.  * | /2 7 /|
  197.  * |A1 6 / |      A_______B
  198.  * | \5 / a| <--- |1 2 3 4|
  199.  * |__C/_)_|      |5 6 7 8|
  200.  *                C-------
  201.  *
  202.  * for each point P1 in the line from C to A
  203.  *    for each point P2 in the perpendicular line starting at P1
  204.  *        get pixel from the source and plot at P2
  205.  *         increment pixel location from source
  206.  * 
  207.  */
  208.  
  209.  
  210. static void copyLine(int x1, int y1, int x2, int y2, int nwidth, int format,
  211.              unsigned char *dst, unsigned char **src)
  212. {
  213.     unsigned char *s = *src;
  214.     int dx, dy;
  215.     int xi, yi;
  216.     int offset;
  217.     int dpr, dpru, p;
  218.     
  219.     dx = abs(x2 - x1);
  220.     dy = abs(y2 - y1);
  221.     
  222.     if (x1 > x2) xi = -1; else xi = 1;
  223.     if (y1 > y2) yi = -1; else yi = 1;
  224.     
  225.     if (dx >= dy) {
  226.     
  227.     dpr = dy << 1;
  228.     dpru = dpr - (dx << 1);
  229.     p = dpr - dx;
  230.     
  231.     while (dx-- >= 0) {
  232.         /* fetch and draw the pixel */
  233.         offset = (x1 + y1 * nwidth) << 2;
  234.         dst[offset++] = *s++;
  235.         dst[offset++] = *s++;
  236.         dst[offset++] = *s++;
  237.         if (format == RRGBAFormat)
  238.         dst[offset++] = *s++;
  239.         else
  240.         dst[offset++] = 255;
  241.  
  242.         /* calc next step */
  243.         if (p > 0) {
  244.         x1 += xi;
  245.         y1 += yi;
  246.         p += dpru;
  247.         } else {
  248.         x1 += xi;
  249.         p += dpr;
  250.         }
  251.     }
  252.     } else {
  253.     
  254.     dpr = dx << 1;
  255.     dpru = dpr - (dy << 1);
  256.     p = dpr - dy;
  257.     
  258.     while (dy-- >= 0) {        
  259.         /* fetch and draw the pixel */
  260.         offset = (x1 + y1 * nwidth) << 2;
  261.         dst[offset++] = *s++;
  262.         dst[offset++] = *s++;
  263.         dst[offset++] = *s++;
  264.         if (format == RRGBAFormat)
  265.         dst[offset++] = *s++;
  266.         else
  267.         dst[offset++] = 255;
  268.  
  269.         /* calc next step */
  270.         if (p > 0) {
  271.         x1 += xi;
  272.         y1 += yi;
  273.         p += dpru;
  274.         } else {
  275.         y1 += yi;
  276.         p += dpr;
  277.         }
  278.     }
  279.     }
  280.  
  281.     
  282.     *src = s;
  283. }
  284.  
  285.  
  286. static RImage *rotateImage(RImage *image, float angle)
  287. {
  288.     RImage *img;
  289.     int nwidth, nheight;
  290.     int x1, y1;
  291.     int x2, y2;
  292.     int dx, dy;
  293.     int xi, yi;
  294.     int xx, yy;
  295.     unsigned char *src, *dst;
  296.     int dpr, dpru, p;
  297.     
  298.     /* only 180o for now */
  299.     if (angle > 180.0)
  300.     angle -= 180.0;
  301.     
  302.     
  303.     angle = (angle * PI) / 180.0;
  304.     
  305.     nwidth = ceil(abs(cos(angle) * image->width))
  306.     + ceil(abs(cos(PI/2 - angle) * image->width));
  307.  
  308.     nheight = ceil(abs(sin(angle) * image->height)) 
  309.     + ceil(abs(cos(PI/2 - angle) * image->height));
  310.     
  311.     img = RCreateImage(nwidth, nheight, True);
  312.     if (!img)
  313.     return NULL;
  314.     
  315.     src = image->data;
  316.     dst = img->data;
  317.     
  318.     x1 = floor(abs(cos(PI/2 - angle)*image->width));
  319.     y1 = 0;
  320.     
  321.     x2 = 0;
  322.     y2 = floor(abs(sin(PI/2 - angle)*image->width));
  323.  
  324.     xx = floor(abs(cos(angle)*image->height)) - 1;
  325.     yy = nheight - 1;
  326.  
  327.     printf("%ix%i, %i %i     %i %i %i\n",
  328.        nwidth, nheight, x1, y1, x2, y2, (int)((angle*180.0)/PI));
  329.     
  330.     dx = abs(x2 - x1);
  331.     dy = abs(y2 - y1);
  332.     
  333.     if (x1 > x2) xi = -1; else xi = 1;
  334.     if (y1 > y2) yi = -1; else yi = 1;
  335.     
  336.     if (dx >= dy) {
  337.     dpr = dy << 1;
  338.     dpru = dpr - (dx << 1);
  339.     p = dpr - dx;
  340.  
  341.     while (dx-- >= 0) {
  342.  
  343.         copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src);
  344.  
  345.         /* calc next step */
  346.  
  347.         if (p > 0) {
  348.         x1 += xi;
  349.         y1 += yi;
  350.         xx += xi;
  351.         yy += yi;
  352.         p += dpru;
  353.         } else {
  354.         x1 += xi;
  355.         xx += xi;
  356.         p += dpr;
  357.         }
  358.     }
  359.     } else {
  360.     puts("NOT IMPLEMTENED");
  361.     return img;
  362.     dpr = dx << 1;
  363.     dpru = dpr - (dy << 1);
  364.     p = dpr - dy;
  365.  
  366.     while (dy-- >= 0) {
  367.         xx = abs(x1*sin(angle*PI/180.0));
  368.         yy = abs(y1*cos(angle*PI/180.0));
  369.  
  370.         copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src);
  371.  
  372.         /* calc next step*/
  373.         if (p > 0) {
  374.         x1 += xi;
  375.         y1 += yi;
  376.         p += dpru;
  377.         } else {
  378.         y1 += yi;
  379.         p += dpr;
  380.         }
  381.     }
  382.     }
  383.     
  384.     return img;
  385. }
  386.